/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package flightlifter;

import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;

/**
 *
 * @author Matt
 */
public class TerrainChunk {

    private int res = 200;
    private int tileSize = 50;
    FloatBuffer verticesFB;
    FloatBuffer uvFB;
    FloatBuffer colorsFB;
    ShortBuffer indicesFB;
    float[] vertices;
    float[] uvs;
    short[] indices;
    float[] colors;

    float[][] heights;

    float maxHeight = 1;

    public TerrainChunk() {

        vertices = new float[3 * res * res];
        colors = new float[3 * res * res];

        uvs = new float[2*res*res];
        indices = new short[4 * (res - 1) * (res - 1)];
        System.out.println(indices.length);

        heights = new float[res][res];
        bump();

        float [] tColor;
        float [] water = {.1f,.1f,.3f};
        float [] land = {.1f,.2f,.0f};
        float [] snow = {.9f,.9f,.9f};

        for (int i = 0; i < res; i++) {
            for (int j = 0; j < res; j++) {

                vertices[i * res * 3 + j * 3] = tileSize * i;
                vertices[i * res * 3 + j * 3 + 1] = maxHeight*heights[i][j];
                vertices[i * res * 3 + j * 3 + 2] = tileSize * j;

                if (heights[i][j] < .01f) tColor = water;
                else if (heights[i][j] < .8f) tColor = land;
                else tColor = snow;

                colors[i * res * 3 + j * 3] = tColor[0];
                colors[i * res * 3 + j * 3 + 1] = tColor[1];
                colors[i * res * 3 + j * 3 + 2] = tColor[2];

                uvs[i * res * 2 + j * 2] = res*((float)i/(float)res);
                uvs[i * res * 2 + j * 2 + 1] = res*((float)j/(float)res);

            }
        }

        for (short i = 0; i < (res - 1); i++) {
            for (short j = 0; j < (res - 1); j++) {

                indices[i * (res - 1) * 4 + j * 4] = (short) (i * res + j + 1);
                indices[i * (res - 1) * 4 + j * 4 + 1] = (short) (i * res + j);
                indices[i * (res - 1) * 4 + j * 4 + 2] = (short) ((i + 1) * res + j);
                indices[i * (res - 1) * 4 + j * 4 + 3] = (short) ((i + 1) * res + j + 1);



            }
        }




        verticesFB = FlightLifter.allocFloats(vertices);
        indicesFB = FlightLifter.allocShorts(indices);
        colorsFB = FlightLifter.allocFloats(colors);
        uvFB = FlightLifter.allocFloats(uvs);


    }
    private float random(float min, float max){
        return min + (max-min)*(float)Math.random();
    }
   private void bump() {

        float z, r, x, y, offset;
        float zmax = 0, zmin = 0;

//clear heights
        for (int i = 0; i < res; i++) {
            for (int j = 0; j < res; j++) {
                heights[i][j] = 0;
            }
        }
        for (int it = 0; it < 5 * res; it++) {
            r = random(.5f, res / 20);
            x = random(0, res);
            y = random(0, res);
            offset = random(0, res);
            

            for (int i = 0; i < res; i++) {
                for (int j = 0; j < res; j++) {
                    z = offset + ((r * r) - ((x - i) * (x - i) + (y - j) * (y - j)));
                    if (z < 0) {
                        z = 0;
                    }
                    heights[i][j] += z;
                    if (heights[i][j] > zmax) {
                        zmax = heights[i][j];
                    }
                    if (heights[i][j] < zmin) {
                        zmin =heights[i][j];
                    }
                }
            }
        }
        
//normalize heights
        for (int i = 0; i < res; i++) {
            for (int j = 0; j < res; j++) {
                heights[i][j] = (heights[i][j] - zmin) / (zmax - zmin);

            }
        }
//create valleys
        for (int i = 0; i < res; i++) {
            for (int j = 0; j < res; j++) {
                heights[i][j] = heights[i][j] * heights[i][j]* heights[i][j];
            }
        }


    }

    public void render() {
        /*

        for (int i = 0; i < res; i++) {
        GL11.glPushMatrix();
        for (int j = 0; j < res; j++) {
        GL11.glPushMatrix();
        GL11.glTranslatef(0, heights[i][j], 0);
        Draw.rect(tileSize, 1);
        GL11.glPopMatrix();
        GL11.glTranslatef(tileSize, 0, 0);

        }
        GL11.glPopMatrix();
        GL11.glTranslatef(0, 0, tileSize);
        }
         */


        //GL20.glUseProgram(0);
        //GL11.glColor3f(1, 1, 1);
        //texture.bind();


        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
        GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);

        GL11.glVertexPointer(3, 0, verticesFB);
        GL11.glTexCoordPointer(2, 0, uvFB);
        GL11.glColorPointer(3, 0, colorsFB);

        GL11.glPushMatrix();
        GL11.glTranslatef(-res*tileSize/2, 0, -res*tileSize/2);
        GL11.glDrawElements(GL11.GL_QUADS, indicesFB);
        GL11.glPopMatrix();

        GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);

    }
}
